Feature: Asset outlets on DAG level for succesfull run - closes [#ISSUE](https://github.com/apache/airflow/issues/39105)#67637
Feature: Asset outlets on DAG level for succesfull run - closes [#ISSUE](https://github.com/apache/airflow/issues/39105)#67637Salfiii wants to merge 22 commits into
Conversation
… and kept the API consistent with how BaseOperator handles outlets. What changed In task-sdk/src/airflow/sdk/definitions/dag.py: 1. Added outlets to DAG init ◦ New field: outlets: list[Any] ◦ Handles both a single outlet and a colection. 2. Added operator-style outlet composition on Dag ◦ DAG.__gt__ now supports dag > outlet ◦ DAG.add_outlets(...) appends validated outlets 3. Wired Dag success to outlet emission ◦ In __attrs_post_init__, if Dag outlets are set, an outlet-emission callback is appended to on_success_callback ◦ Existing user callbacks are preserved ◦ has_on_success_callback is updated 4. Added the callback implementation ◦ Emits asset events when a Dag run succeeds ◦ Only emits concrete Asset outlets ◦ Includes Dag/run source metadata ◦ Creates missing asset models before retrying event registration (same pattern as task outlet handling) In airflow-core/src/airflow/assets/manager.py: 5. Extended register_asset_change(...) so Dag-level emitters can provide source fields directly ◦ Added optional args: ▪ source_dag_id ▪ source_task_id ▪ source_run_id ▪ source_map_index ◦ Task-instance flow is unchanged ◦ This lets Dag-level events carry proper provenance without pretending to come from a task In task-sdk/tests/task_sdk/definitions/test_dag.py: 6. Added tests for: ◦ outlets init from single value ◦ outlets init from collection ◦ dag > outlet ◦ rejecting invalid outlet input ◦ auto-registration of Dag success outlet callback ◦ preserving existing success callback when outlets are enabled Why The issue asks for Dag-level outlets with the same practical effect as operator outlets, but triggered when the Dag run succeeds. This change gives you that behavior while keeping the Dag API familiar (outlets=..., dag > outlet) and making sure emitted events are traceable back to the Dag run.
Treat string values passed through dag > outlet as a single invalid outlet instead of iterating over characters. Import Asset where Dag-level outlet event emission checks for concrete assets, and update the invalid-outlet test to exercise DAG.__gt__ without triggering ruff’s pointless-comparison rule.
|
Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
|
|
@Salfiii A few things need addressing before review — see our Pull Request quality criteria.
No rush. Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you. |
|
@Salfiii Converting to draft — this PR does not yet meet our Pull Request quality criteria. See the linked criteria for how to fix each item, then mark the PR "Ready for review". This is not a rejection — just an invitation to bring the PR up to standard. No rush. Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you. |
|
hi @potiuk , I´ll try to fix everything you mentioned, my problem is that i´m currently bound to a windows environment for development, which makes it quite challenging to run all the necessary checks on my side. I can still confirm that the introduced scheduling logic works though. best regards |
|
Hi @potiuk, I think i got all Pre-commit / static checks to run and applied some updates. best regards |
Fix serialized Dag outlets compatibility
Fix serialized Dag outlet defaults
Keep serialized Dag schema in sync
|
Hi @potiuk , I fixed the serialization problems, are you willing to take another look at the PR? Thanks a lot for your patience. Best regards |
|
@Salfiii This PR has a few issues that need to be addressed before it can be reviewed — please see our Pull Request quality criteria. Issues found:
What to do next:
There is no rush — take your time and work at your own pace. We appreciate your contribution and are happy to wait for updates. If you have questions, feel free to ask on the Airflow Slack. Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you. |
Implemented Dag-level outles in Task SDK based on issue #39105, and kept the API consistent with how BaseOperator handles outlets.
We need a possiblity to trigger other dags by a successfully dag run and I came across the proposal in above issue that would solve our needs without manually implementing a specific fan-in/notification task at the end of every dag and it also fits the new Asset approach of airflow.
I tried to respect the guidlines in the comments of said issue.
Changes:
In task-sdk/src/airflow/sdk/definitions/dag.py:
1.Added outlets to DAG init
◦New field: outlets: list[Any]
◦Handles both a single outlet and a colection.
2.Added operator-style outlet composition on Dag
◦DAG.gt now supports dag > outlet
◦DAG.add_outlets(...) appends validated outlets
3.Wired Dag success to outlet emission
◦In attrs_post_init, if Dag outlets are set, an outlet-emission callback is appended to on_success_callback
◦Existing user callbacks are preserved
◦has_on_success_callback is updated
4.Added the callback implementation
◦Emits asset events when a Dag run succeeds
◦Only emits concrete Asset outlets
◦Includes Dag/run source metadata
◦Creates missing asset models before retrying event registration (same pattern as task outlet handling)
In airflow-core/src/airflow/assets/manager.py:
5.Extended register_asset_change(...) so Dag-level emitters can provide source fields directly. This makes outlets/events traceable to dag-runs ( I hope thats ok=
◦Added optional args:
▪source_dag_id
▪source_task_id
▪source_run_id
▪source_map_index
◦Task-instance flow is unchanged
Added tests for:
◦outlets init from single value
◦outlets init from collection
◦dag > outlet
◦rejecting invalid outlet input
◦auto-registration of Dag success outlet callback
◦preserving existing success callback when outlets are enabled
Why
The issue asks for Dag-level outlets with the same practical effect as operator outlets, but triggered when the Dag run succeeds.
-->
Was generative AI tooling used to co-author this PR?
Generated-by: Codex via Jetbrains AI Assistant following the guidelines
Gen-Ai was mainly used to explain the outlets structure of baseOperator and to understand on how to integrate the same approach into the DAG because the codebase is quite complex.
Important
🛠️ Maintainer triage note for @Salfiii · by
@potiuk· 2026-07-02 17:38 UTCHelpful heads-up from the maintainers — please address before this PR can be reviewed (see the Pull Request quality criteria):
CI image checks / Build documentation (--spellcheck-only),CI image checks / Static checks. Run them locally withpre-commit/prekand push the fixes.MySQL tests: core / DB-core:MySQL:8.0:3.10:Core...Serialization,Postgres tests: core / DB-core:Postgres:14:3.10:Core...Serialization,Sqlite tests: core / DB-core:Sqlite:3.10:Core...Serialization,provider distributions tests / Compat 2.11.1:P3.10:,provider distributions tests / Compat 3.0.6:P3.10:,provider distributions tests / Compat 3.1.8:P3.10:. Please investigate and push a fix.The ball is in your court — you've been assigned to this PR. Fix the above, then mark it Ready for review.
Automated triage — may be imperfect; a maintainer takes the next look.